侯捷CPP面向对象高级开发笔记整理

C++面向对象高级开发(上)

一、C++编程简介

(1)基于对象:只有一个class的编程 object based

面向对象:几个class(有继承和组合等关系)的编程 object oriented

(2)class的经典分类:

class without pointer members ——>e.g: complex 复数

class with pointer members ——>e.g: string 字符串

没有指针成员的类通常不需写析构函数。

(3)class之间的关系:继承inheritance、复合composition、委托delegation

(4)学习C++,分为学习C++语言,和C++标准库

(5)C++书籍:语言的书籍《C++Primer》第五版,《C++programming Language》第四版

提高书籍:《Effective C++ Third Edition》及中文版 《The C++ Standard Library》《STL源码剖析》(STL是标准库的前身)

二、头文件与类的声明

(1)标准库以头文件的形式存在,只需要include进去就好#include <*.h>

(2)C语言 #include<stdio.h> 或者 #include<cstdio>,而 C++: #include<iostream>或者 #include<iostream.h>

(3)头文件的布局:

#ifndef __complex__

#define __complex__

*******

##endif

(4)class的布局:

class header

class body

三、构造函数

(1)inline函数:只要成员函数在class body里面定义,不需要显示声明,就是inline函数,而如果在body之外定义,要想成为inline函数,必须显示声明。是否成为inline函数,由编译器来决定,即使声明为inline function,也不一定编译器有能力使之成为inline function。

(2)access level 访问级别:public ,private ,protected

类域控制,是类外还是类内,在其它函数如主函数中定义类对象,用对象引用数据成员时,如果数据成员是private的,因为是类外,所以也是非法的。

private:数据的部分用尽量用private

public:函数的部分,大部分用public

(3)构造函数 :创建一个对象的时候,构造函数自动被调用,构造函数可设置默然参数,并用冒号设置参数初始化列表:

pair(const T1& a, const T2& b) : first(a), second(b) {}

两个阶段:初始化、{}内的赋值;

参数initializition list和在body里对参数赋值的区别:一个是参数初始化;一个是赋值,是一个执行的过程,多了计算量;

创建一个对象,可以有参数,也可以无参数,也可动态创建:complex *p = new complex(4);

class定义了多个构造函数,就是重载overloading

(4)友元函数:

四、参数传递和返回值

1、数据放在private里

2、参数用reference,是否用const

3、返回值用reference传

4、在类的body里的函数是否加const

5、构造函数的 initial list

五、操作符重载与临时对象

1,、所有的成员的函数带有一个隐藏的参数“this”,谁调用这个函数谁就是 this

临时对象 complex() ——》typename();

2、在类外

Complex Complex::operator+=(complex &c2)

这个是成员函数 operator+= 的实现,所以需要 Complex:: ,具有this指针。例如:

inline complex&

complex::operator += (const complex& r)

{

return __doapl (this, r);

}

而下面属于运算符重载,不是成员函数的时候,就没有Complex:: 。

inline complex

operator - (const complex& x, double y)

{

return complex (real (x) - y, imag (x));

}

六、复习Complex类的实现过程

七、三大函数:拷贝构造,拷贝赋值,析构

构造函数

拷贝构造函数

拷贝赋值函数

析构函数

——》只要类带有指针,就一定需要拷贝构造函数和 拷贝赋值函数

浅拷贝——》拷贝构造函数,浅拷贝的影响:1、造成内存泄漏;2、造成有两个指针指向同一块内存

深拷贝——》拷贝赋值函数步骤:delete ;new; strcpy;

class里面有默认的拷贝构造和拷贝赋值函数。如果自己不定义一个拷贝构造函数,在调用拷贝构造函数的时候,就会调用默认的浅拷贝构造函数,就会造成问题,所以一定要自己定义拷贝构造函数——深拷贝。

八、堆,栈与内存管理

1、static local objects的生命周期

static的生命周期 :object的对象在scope结束以后仍然存在,直到整个程序结束;

非static 的生命周期:object的对象在在scope结束以后就结束了。

global objects的生命周期:

对象 objects 生命结束,就是什么时候析构函数被调用:

2、new——》operator new。new动态创建对象,分三步:第一步,先转化为operator new 函数,申请分配内存。第二步,做类型转化。第三步,调用构造函数

delete ——》operator delete。删除对象,分两步:第一步,先调用析构函数,第二步,再调用operator delete函数。

3、带中括号[ ]的new[ ]叫做array new,带中括号[ ]的delete[ ] 叫做array delete。

动态分配所得到的数组array:complex *p = new complex[3];

new [] ——》delete[] ——》表示调用几次析构函数

new 字符串 ——》delete 指针

delete[n] :array new一定要调用array delete,delete[n]会调用n次析构函数,而delete仅调用一次。

十、扩展补充:类模板,函数模板,及其他

(1)static :静态数据不属于某一个对象,而非静态的是属于一个对象的,这种情况需要设置为静态数据。

静态函数没有this pointer,而非静态函数有 this pointer,可以用this去取数据,静态函数要处理数据只能处理静态数据。

静态数据一定要在class外面定义。

给变量赋值,使获得内存的过程叫定义。

(2)template:类模板函数模板

(3)namespace:

十一、复合与继承

(1)复合composition关系下的构造和析构:构造是由内而外,析构是由外而内 has-a,即先调用component的构造函数,再调用container的构造函数。

计算内存的大小:复合类component的内存大小+container的内存大小

(2)委托delegation,即composition by reference:在body中声明一个带指针的另一个类 composition by reference

生命时间: classA 用一个指针指向classB,需要的时候才调用classB,而不是一直拥有classB。

(3)继承Inheritance:(三种继承方式:public protected private)is-a,继承主要搭配虚函数来使用

函数的继承:指的是继承函数的调用权,子类可以调用父类的函数。

计算内存的大小:先调用父类的构造函数,再调用子类的构造函数。先调用子类的析构,再调用父类的析构函数。

十二、虚函数与多态

(1)虚函数:virtual

纯虚函数:一定要重新定义。

(2)

(A)Inheritance + composition下的构造和析构

(B)delegation + Inheritance ——》 功能最强大的一种

十三、委托相关设计

侯捷 C++面向对象高级开发(下)笔记整理

一、导读

(1)泛型编程和面向对象编程分属不同的思维,

(2)由继承关系所形成的对象模型,包含this指针,vptr指针,vtbl虚表,虚机制,以及虚函数造成的多态。

二、conversion function 转换函数

(1)通过指定关键字operator,如operator type() const {} ,并在其后加上转换的目标类型后,我们就可以声明转换函数。转换函数必须是成员函数,它的声明不能指定返回类型和参数列表。

分数Fraction型转换成double型,返回类型不用写,默认为double型,没有形参。

三、non-explicit-one-argument constructor

(1)explicit这个关键字基本只出现在构造函数前面,意思是需要明确地需要调用这个构造函数才能调用,不存在暗中、自动的转换操作。

构造函数两个参数,第二个参数有个默认值为1;one-argument表示只需要一个实参就可以调用该函数

四、pointer-like classes 智能指针

(1)比指针更高级一些的。C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。程序员自己管理堆内存可以提高了程序的效率,但是整体来说堆内存的管理是麻烦的,C++11中引入了智能指针的概念,方便管理堆内存。

(2)智能指针在C++11版本之后提供,包含在头文件中,shared_ptr、unique_ptr、weak_ptr

五、function-like classes 仿函数

(1)其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

六、namespace经验谈

七、class template 类模板

八、Funtion Template 函数模板

九、Member Template 成员模板

(1)模板里面再定义模板

十、specialization 模板特化

(1)template <> ——》<>里面没有类型的参数了,参数类型在后面绑定,即特化

template ——》泛化

十一、partial specialization 模板偏特化

(1)template

class vector { //…//};

这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。

(2)偏特化分:类模板偏特化、 函数模板偏特化

十二、模板模板参数

(1)模板的参数类型也是模板

(2) template 和 template ,只有这template <>尖括号里,class和 typename可以互相替换。typename是后来发展出来的,由于历史原因,保留着两种写法。

十三、关于C++标准库

(1)容器Container,就是数据结构:数组,列表,队列......

(2)算法Algorithms

十四、三个主题( 和C++11有关)

(1)variadic templates 数量不定的模板参数,即模板参数可变化

例:template

(2)auto 编译器可以指导变量的类型,就在变量前面加上auto

(3)ranged-base for 即for循环的新形式

例:for( int i : {1, 2, 3, 4, 5, } ) { }

十五、Reference

(1)变量占内存,指针变量 int* p = &k,p里面存放的 k 是地址;

(2)int& r=k;变量r代表k的值,r在声明的时候一定要有初值。且在此 int& r=k 之后,不能再变化,指向其他的变量。

下面讲的是对象模型Object Model——》即class和class之间的关系

十六、复合&继承关系下的构造和析构

(1)Inheritance下的构造和析构,从内存的角度去分析,子类包含父类的成分和特性,即变量和函数

(2)composition下的构造和析构

(3)Inheritance+composition下的构造和析构

十七、关于vptr和vtbl

(1)多态,

十八、关于this

(1)通过一个对象来调用一个函数,那么对象的地址就是this pointer。

关于Dynamic Binding 19 (1)

(1)const成员函数,不修改成员变量;

double real () const { return re; }

关于Dynamic Binding

(2)new 创建一个新的对象。

B b;

A a = (A)b;

a.vfunc1();——》通过对象a来调用虚函数vfunc1(),而不是通过指针来调用,属于静态绑定,所以调用的是A的虚函数

A* pa = new B;——》new出来的对象作向上转型为A ,pa就是this pointer,调用的是A的虚函数。

pa ->vfunc1();

pa = &b; ——》向上转型

pa ->vfunc1(); ——》动态绑定;

符合动态绑定的三个条件:a,指针;b,虚函数;c,向上转型;

二十、关于New,Delete

new分解为三个动作malloc ,delete分解为两个动作 free 。

(1)new 和delete,

new先分配内存,再调用构造函数

delete先调用析构函数,再释放memory。

(2)new [ ] 和delete[ ]

二十一、Operator new,operator delete

(1)全局的重载

重载::operator new 和::operator delete

重载v::operator new [ ] 和 ::operator delete[ ]

(2)在class里重载

重载::operator new (size_t) 和::operator delete()

重载v::operator new [ ](size_t) 和 ::operator delete[ ] ()

二十二、示例

二十三、重载new(),delete()$示例

二十四、Basic_String使用new(extra)扩充申请量

(1)new有四种:操作符new,operator new ,new[ ](即array new)和 placement new

本页共196段,7845个字符,13855 Byte(字节)